﻿using System;
using System.Runtime.InteropServices;

namespace H2o
{
    internal enum RasFieldSizeConstants
    {
        RAS_MaxDeviceType = 16,
        RAS_MaxPhoneNumber = 128,
        RAS_MaxIpAddress = 15,
        RAS_MaxIpxAddress = 21,
#if WINVER4
		RAS_MaxEntryName      =256,
		RAS_MaxDeviceName     =128,
		RAS_MaxCallbackNumber =RAS_MaxPhoneNumber,
#else
        RAS_MaxEntryName = 20,
        RAS_MaxDeviceName = 32,
        RAS_MaxCallbackNumber = 48,
#endif

        RAS_MaxAreaCode = 10,
        RAS_MaxPadType = 32,
        RAS_MaxX25Address = 200,
        RAS_MaxFacilities = 200,
        RAS_MaxUserData = 200,
        RAS_MaxReplyMessage = 1024,
        RAS_MaxDnsSuffix = 256,
        UNLEN = 256,
        PWLEN = 256,
        DNLEN = 15,

        INTERNET_RAS_INSTALLED = 0x10,
        RAS_Connected = 0x2000
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct GUID
    {
        public uint Data1;
        public ushort Data2;
        public ushort Data3;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] Data4;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct RASCONN
    {
        public int dwSize;
        public IntPtr hrasconn;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxEntryName + 1)]
        public string szEntryName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxDeviceType + 1)]
        public string szDeviceType;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxDeviceName + 1)]
        public string szDeviceName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]//MAX_PAPTH=260
        public string szPhonebook;
        public int dwSubEntry;
        public GUID guidEntry;
#if (WINVER501)
		 int     dwFlags;
		 public LUID      luid;
#endif
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct LUID
    {
        int LowPart;
        int HighPart;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class RasStats
    {
        public int dwSize = Marshal.SizeOf(typeof(RasStats));
        public int dwBytesXmited;
        public int dwBytesRcved;
        public int dwFramesXmited;
        public int dwFramesRcved;
        public int dwCrcErr;
        public int dwTimeoutErr;
        public int dwAlignmentErr;
        public int dwHardwareOverrunErr;
        public int dwFramingErr;
        public int dwBufferOverrunErr;
        public int dwCompressionRatioIn;
        public int dwCompressionRatioOut;
        public int dwBps;
        public int dwConnectDuration;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class RASPPPIP
    {
        public uint dwSize = 72;
        public uint dwError;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string szIpAddress;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string szServerIpAddress;
    }

    public enum RASPROJECTION : uint
    {
        RASP_AMB = 0x10000,
        RASP_PppNbf = 0x803F,
        RASP_PppIpx = 0x802B,
        RASP_PppIp = 0x8021,
        RASP_PppCcp = 0x80FD,
        RASP_PppLcp = 0xC021,
        RASP_Slip = 0x20000

    }

    public class RAS
    {

        [DllImport("Rasapi32.dll", EntryPoint = "RasEnumConnectionsA",
             SetLastError = true)]
        internal static extern int RasEnumConnections
            (
                ref RASCONN lprasconn, // buffer to receive connections data
                ref int lpcb, // size in bytes of buffer
                ref int lpcConnections // number of connections written to buffer
            );

        [DllImport("rasapi32.dll", CharSet = CharSet.Auto)]
        internal static extern uint RasGetConnectionStatistics(
            IntPtr hRasConn,       // handle to the connection
            [In, Out]RasStats lpStatistics  // buffer to receive statistics
            );

        [DllImport("rasapi32.dll", CharSet = CharSet.Auto)]
        public extern static uint RasHangUp(
            IntPtr hrasconn  // handle to the RAS connection to hang up
            );

        [DllImport("wininet.dll", CharSet = CharSet.Auto)]
        public extern static int InternetDial(
            IntPtr hwnd,
            [In]string lpszConnectoid,
            uint dwFlags,
            ref int lpdwConnection,
            uint dwReserved
            );


        [DllImport("WININET", CharSet = CharSet.Auto)]
        public static extern bool InternetGetConnectedState(
            ref int lpdwFlags,
            int dwReserved);

        [DllImport("rasapi32.dll", CharSet = CharSet.Auto)]
        public extern static uint RasGetProjectionInfo(
            IntPtr hRasConn,
            RASPROJECTION projection,
            [In, Out] RASPPPIP pppip,
            ref uint ppipSize
            );

        public RAS()
        { }
    }

    public class RASDisplay
    {
        int Empty = 0;
        uint INTERNET_AUTO_DIAL_UNATTENDED = 2;
        int lpcb = 0;
        int lpcConnections = 0;


        public IntPtr Connected()
        {

            RASCONN lprasConn = new RASCONN();

            lprasConn.dwSize = Marshal.SizeOf(typeof(RASCONN));
            lprasConn.hrasconn = IntPtr.Zero;

            int nRet = 0;
            lpcb = Marshal.SizeOf(typeof(RASCONN));

            //获得连接
            nRet = RAS.RasEnumConnections(ref lprasConn, ref lpcb, ref
				lpcConnections);

            if (nRet != 0)
            {
                return IntPtr.Zero;
            }
            return lprasConn.hrasconn;

        }
        // 获得连接在线时间
        //public string Duration()
        //{
        //    IntPtr conn = Connected();
        //    if (conn != IntPtr.Zero)
        //    {
        //        RasStats stats = new RasStats();
        //        RAS.RasGetConnectionStatistics(conn, stats);
        //        int Hours, Minutes, Seconds = 0;

        //        Hours = ((stats.dwConnectDuration / 1000) / 3600);
        //        Minutes = ((stats.dwConnectDuration / 1000) / 60) - (Hours * 60);
        //        Seconds = ((stats.dwConnectDuration / 1000)) - (Minutes * 60) - (Hours * 3600);
        //        return Hours + " hours " + Minutes + " minutes " + Seconds + " secs";

        //    }
        //    return "Not Connect";
        //}

        public string getIPAddress()
        {
            IntPtr conn = Connected();


            RASPPPIP pppip = new RASPPPIP();
            uint size = (uint)Marshal.SizeOf(typeof(RASPPPIP));
            pppip.dwSize = size;
            uint ipstatus = 0;
            ipstatus = RAS.RasGetProjectionInfo(conn, RASPROJECTION.RASP_PppIp, pppip, ref size);
            if (ipstatus == 0)
            {
                return pppip.szIpAddress;
            }
            else
            {
                return "Not Connect";
            }
        }

        public int Connect(string Connection)
        {

            int retVal = RAS.InternetDial(IntPtr.Zero, Connection, INTERNET_AUTO_DIAL_UNATTENDED, ref Empty, 0);
            return retVal;
        }


        /// <summary>
        /// 关闭所有拨号网络链接
        /// </summary>
        public void Disconnect()
        {
            int flags = 0;
            RAS.InternetGetConnectedState(ref flags, 0);
            if (!((flags & (int)RasFieldSizeConstants.INTERNET_RAS_INSTALLED)
                == (int)RasFieldSizeConstants.INTERNET_RAS_INSTALLED))
                throw new NotSupportedException();

            IntPtr conn = Connected();
            if (conn != IntPtr.Zero)
            {
                RAS.RasHangUp(conn);
            }

        }
    }
}
